<template>
  <div class="els-codemirror">
    <div v-if="showHeader" class="c--header">
      <div class="h--left">
        <slot name="menuLeft">
          {{title}}
        </slot>
      </div>
      <div class="h--right">
        <slot name="menuRight">
          <el-button type="text" :icon="onlyRead?'el-icon-edit':'el-icon-view'" @click.stop="onlyRead = !onlyRead">
            {{ onlyRead?'编辑':'只读'}}
          </el-button>
          <el-button type="text" icon="el-icon-refresh" @click.stop="handleSave">刷新</el-button>
          <el-button type="text" icon="el-icon-c-scale-to-original" @click.stop="handleFormat">格式化</el-button>
        </slot>
      </div>
    </div>
    <div class="c--main">
      <codemirror ref="codemirrorRef" :value="text" :options="option" @changes="handleChange"></codemirror>
    </div>
  </div>
</template>

<script>
import { codemirror } from "vue-codemirror";
import "codemirror-formatting/formatting.js"
import "codemirror/lib/codemirror.css";
import 'codemirror/mode/javascript/javascript' // 这js模式必须引入的

import 'codemirror/addon/selection/active-line' //光标行背景高亮，配置里面也需要styleActiveLine设置为true
import 'codemirror/keymap/sublime' //sublime编辑器效果
import 'codemirror/mode/css/css'
import 'codemirror/theme/monokai.css' //编辑器主题样式，配置里面theme需要设置monokai
import 'codemirror/mode/meta'
//语言包
import 'codemirror/mode/clike/clike'
import 'codemirror/mode/go/go'
import 'codemirror/mode/htmlmixed/htmlmixed'
import 'codemirror/mode/http/http'
import 'codemirror/mode/php/php'
import 'codemirror/mode/python/python'
import 'codemirror/mode/http/http'
import 'codemirror/mode/sql/sql'
import 'codemirror/mode/vue/vue'
import 'codemirror/mode/xml/xml'
//下面这几个引入的主要是验证提示类的,配置里的lint需要设置true,gutters: ['CodeMirror-lint-markers']
import 'codemirror/addon/lint/lint'
import 'codemirror/addon/lint/lint.css'
import 'codemirror/addon/lint/json-lint'
import 'codemirror/addon/display/autorefresh'
//
import 'codemirror/addon/hint/show-hint'
import 'codemirror/addon/hint/javascript-hint'
import 'codemirror/addon/hint/sql-hint'
import 'codemirror/addon/hint/html-hint'
import 'codemirror/addon/hint/xml-hint'
import 'codemirror/addon/hint/anyword-hint'
import 'codemirror/addon/hint/css-hint'
import 'codemirror/addon/hint/show-hint.css'
// 折叠
import 'codemirror/addon/fold/foldgutter.css'
import 'codemirror/addon/fold/foldcode'
import 'codemirror/addon/fold/foldgutter'
import 'codemirror/addon/fold/brace-fold'
import 'codemirror/addon/fold/comment-fold'
import 'codemirror/addon/fold/indent-fold'
import 'codemirror/addon/fold/markdown-fold'
import 'codemirror/addon/fold/xml-fold'


export default {
  name:'els-codemirror',
  components: {codemirror},
  props:{
    title:String,
    format:Function,
    mode:{type:[Object,String],default:() => ({name:"text/html"})},
    value:{type:String,default:''},
    options:{type:Object,default:() => ({})},
    readOnly:{type:Boolean,default:true},
    showHeader:{type:Boolean,default:true},
  },
  data:() => ({
    initValue:'',
    text:'',
    onlyRead:true,
    editor:null,
  }),
  computed:{
    option(){
      const ops = this.options;
      const d = {
        theme: "monokai",
        mode:this.mode,
        value: this.initValue,
        lineNumbers: true,
        lineWiseCopyCut: true,
        showCursorWhenSelecting: true,
        matchBrackets: true,
        lineWrapping: true,
        foldGutter: true, // 块槽
        gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
        line: true,
        readOnly:this.onlyRead,
        autoRefresh:true,
      }
      return {...d,...ops}
    }
  },
  methods:{
    //
    handleChange(c,o){
      this.text = c.doc.getValue()
      this.$emit('input',this.text)
      // this.autoFormat();
    },
    //
    handleSave(){
      this.$emit('submit',this.text)
    },
    //
    handleFormat(){
      this.autoFormat();
    },
    utilSetEditorValue(v){
      if(this.format){
        v = this.format(v);
      }
      this.editor.setValue(v)
    },
    autoFormat(){
      const lc = this.editor.lineCount();
      const from = {ch:0,line:0}
      const to = {ch:0,line:lc}
      this.editor.autoFormatRange(from, to);
    },
  },
  created(){
    this.onlyRead = this.readOnly;
    this.text = this.value
  },
  mounted(){
    this.initValue = this.value;
    this.editor = this.$refs.codemirrorRef.codemirror
    //
    this.autoFormat();
  },
  watch:{
    value(){
      if(this.value !== this.text){
        this.text = this.value;
        this.utilSetEditorValue(this.text)
        this.$nextTick(() => {
          this.autoFormat();
        })
      }
    }
  }
}
</script>

<style scoped lang="scss">
  .els-codemirror{
    width:100%;
    height:100%;
    border:1px solid #ddd;
    border-radius: 8px;
    box-sizing: border-box;
    overflow: hidden;
    .c--header{
      display: flex;
      justify-content: space-between;
      align-items: center;
      height:48px;
      box-sizing: border-box;
      border-bottom:1px solid #ddd;
      background:#f7f7f7;
      .h--left{
        margin-left:1em;
      }
      .h--right{
        margin-right:1em;
      }
    }
    .c--main{
      width:100%;
      height:calc(100% - 48px);
    }
  }
</style>
